package com.imu.utils;

import java.security.InvalidKeyException;
import java.security.KeyPair;
import java.security.PrivateKey;
import java.security.PublicKey;
import java.security.Signature;
import java.security.SignatureException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.util.StringUtils;

import com.imu.common.exception.RRException;
import com.xiaoleilu.hutool.crypto.SecureUtil;
import com.xiaoleilu.hutool.crypto.asymmetric.AsymmetricAlgorithm;
import com.xiaoleilu.hutool.crypto.digest.DigestAlgorithm;
import com.xiaoleilu.hutool.lang.Base64;
import com.xiaoleilu.hutool.util.HexUtil;

/**
 * Created by sunhw on 2017/08/21.
 * @author sunhongwei
 * @email sunhongwei@gmail.com
 * @date 2017年11月4日 上午11:07:35
 */
public class RSASignature 
{
	/****
     * 签名
     * @param body 签名字符串 
     * @param key 私钥
     * @return
     */
    public static String sign(String body, String key)
    {
    	String sign = null;
    	
    	try 
        {
    		logger.info("request body = {}", body);
    		
    		if(StringUtils.isEmpty(body))
        	{
        		throw new RRException("参数不能为空", 512);
        	}
    		
    		PrivateKey privateKey = SecureUtil.generatePrivateKey(AsymmetricAlgorithm.RSA.getValue(), Base64.decode(key));
        	Signature signature = SecureUtil.generateSignature(AsymmetricAlgorithm.RSA, DigestAlgorithm.SHA256);
        	signature.initSign(privateKey);  
            signature.update(body.getBytes());
        	sign = Base64.encode(HexUtil.encodeHexStr(signature.sign()));
        } 
        catch (Exception e) 
        {
        	logger.error("签名失败....", e);
		}

    	return sign;
    }
    
    /****
     * 验证签名
     * @param dto
     * @param sign
     * @return
     */
    public static boolean verifySign(String body, String sign, String key)
    {
    	try 
        {
    		logger.info("request body = {}, sign = {}", body , sign);
    		if(StringUtils.isEmpty(body))
        	{
        		throw new RRException("参数不能为空", 512);
        	}
    		
	        if(StringUtils.isEmpty(sign))
	        {
	            throw new RRException("签名不能为空...", 460);
	        }
	    
	    	if(verify(body.getBytes(), sign, key))
	     	{
	    		return true;
	        }
        } 
        catch (Exception e) 
        {
        	logger.error("解签失败...", e);
		}

    	return false;
    }
	
    /****
     * 验证MD5 是否正确
     * @param dto
     * @param md5
     * @param sign
     * @return
     */
    public static boolean verifySign(String body, String md5, String sign, String key)
    {
    	try 
        {
    		logger.info("request body = {}, sign = {}", body , sign);
    		
    		if(StringUtils.isEmpty(body))
        	{
        		throw new RRException("参数不能为空", 512);
        	}
    		
	        if(StringUtils.isEmpty(md5) || StringUtils.isEmpty(sign))
	        {
	            throw new RRException("签名不能为空...", 460);
	        }
	    
	    	if(SecureUtil.md5(body).equals(md5) && verify(body.getBytes(), sign, key))
	     	{
	    		return true;
	        }
        } 
        catch (Exception e) 
        {
        	logger.error("解密失败....", e);
		}

    	return false;
    }
    
    /****
     * 验证签名
     * @param body
     * @param sign
     * @return
     * @throws InvalidKeyException
     * @throws SignatureException
     */
    private static boolean verify(byte[] body, String sign, String key) throws InvalidKeyException, SignatureException
    {
    	PublicKey publicKey = SecureUtil.generatePublicKey(AsymmetricAlgorithm.RSA.getValue(), Base64.decode(key));
    	Signature signature = SecureUtil.generateSignature(AsymmetricAlgorithm.RSA, DigestAlgorithm.SHA256);
    	signature.initVerify(publicKey);
        signature.update(body);
    	return signature.verify(HexUtil.decodeHex(Base64.decodeStr(sign)));
    }

    public static void main(String agrs[]) throws Exception
    {
    	KeyPair keyPair = SecureUtil.generateKeyPair(AsymmetricAlgorithm.RSA.getValue(), SecureUtil.DEFAULT_KEY_SIZE);
    	PublicKey  publicKey  = keyPair.getPublic();
    	PrivateKey privateKey = keyPair.getPrivate();
    	
    	String pubKey,priKey;
    	//System.out.println(pubKey = Base64.encode(publicKey.getEncoded()));
    	//System.out.println(priKey = Base64.encode(privateKey.getEncoded()));

    	priKey = "MIICdwIBADANBgkqhkiG9w0BAQEFAASCAmEwggJdAgEAAoGBALymXlL8dgo9UTs+y//3P4gV1SHWsLgP4eqCpRQiXrZkvt0+j7cED+KESFUAGfw++hsnJUGqnWRvn6nGLrGn0AxPK+QAEg7In9PcwpgYlKV7oPQPBuFs1XwF7R5TIvBoDt1R/ACzJ7jMxRTx+2vsXp5EbiYcbHDXThMLZxVf64QDAgMBAAECgYEAjxpc3vKn0CinYBvIwAicZuy42oxzTYyuwSgNdXKFCjLuHgKBHkG0kw3pmKEVFSXor4RIXMHB1xhds3mknhtAU2hojp0jfxhJnaZHnQ+agU87b3DyqnnTqI9CIOLkRYTqDJVSzkKAcUXFkyPl4+a0v11gbIiogzbYoxaMZcf+jIECQQDklNeeVO1L8R+WbsKhhjKHFgdhstl3xVvfSROoERRmqeKVc6YM1DVoEJgey0LUxdk+DTh48Egf7figtGUYMQYhAkEA00dUXMjRoWJT6yz1d8JN896RnLSLjeClR7zprPLQ/WPxHDZwT9e4tbD4ka6Hd+NihodvtVE73YNWCpdahOb9owJBAIAg7rxR3rIy9wHcFD12e9w8/OZG2p/IgTcoP1x2NnlVwS0FJo8KZOVwZ9TbGxspzBx8TKt+BO/g9P0gIYrt8AECQDstG1/xj2WYWNDiAs7MSXEowbgWiY/vf9ub+gdK62ZNe9bfGI4EaePZ8YU8UQ0vTwVHIe6zFgVxJ8RHqD7ZQ+kCQEKWH7P/aaS8iLF9f1d5lsor+uPIq5o5j3FmbRFJdKc8NnrAE6h9+hGNe73oxn1iSA9jmhFJZ+nbPskpaSSFL70=";
    	pubKey = "MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQC8pl5S/HYKPVE7Psv/9z+IFdUh1rC4D+HqgqUUIl62ZL7dPo+3BA/ihEhVABn8PvobJyVBqp1kb5+pxi6xp9AMTyvkABIOyJ/T3MKYGJSle6D0DwbhbNV8Be0eUyLwaA7dUfwAsye4zMUU8ftr7F6eRG4mHGxw104TC2cVX+uEAwIDAQAB";
    	
    	String sign;
    	String body = "{\"zone\": \"0086\",\"phone\": \"17607159920\",\"type\": 0,\"cs\": 1532569881}";
    	System.out.println(sign = sign(body, priKey));
		System.out.println("签名"+sign);
    	System.out.println(verifySign(body, sign, pubKey));
    }
    
    //日志记录
    private static final Logger logger = LoggerFactory.getLogger(RSASignature.class);
}